home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfsrecov / usage.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-17  |  9.5 KB  |  356 lines

  1. /* 
  2.  * usage.c --
  3.  *
  4.  *    Segment usage manipulation routines for the lfsrecov program.
  5.  *
  6.  * Copyright 1991 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that this copyright
  10.  * notice appears in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/proto.c,v 1.5 91/02/09 13:24:44 ouster Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "lfslib.h"
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <sys/file.h>
  24. #include <option.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <alloca.h>
  28. #include <bstring.h>
  29. #include <unistd.h>
  30. #include <bit.h>
  31. #include <time.h>
  32. #include <sys/time.h>
  33. #include <assert.h>
  34. #include <hash.h>
  35. #include <libc.h>
  36.  
  37. #include "lfsrecov.h"
  38. #include "usage.h"
  39.  
  40.  
  41. typedef struct SegInfo { 
  42.     int    logPosition;    /* Current position to the list of segment written since
  43.              * the last checkpoint. */
  44.     int    startLogBlockOffset; /* Starting block offset into segment of log. Only
  45.                   * valid if logPosition is nonzero. */
  46.  
  47. } SegInfo;
  48. static SegInfo    *segInfoArray = (SegInfo *) NULL;
  49. static int logPosition = 0;
  50.  
  51.  
  52. /*
  53.  *----------------------------------------------------------------------
  54.  *
  55.  * RecordSegInLog --
  56.  *
  57.  *    Record the fact that the specified segment is part of the 
  58.  *    recovery log.
  59.  *
  60.  * Results:
  61.  *    None.
  62.  *
  63.  * Side effects:
  64.  *    None.
  65.  *
  66.  *----------------------------------------------------------------------
  67.  */
  68.  
  69. void
  70. RecordSegInLog(segNo, blockOffset)
  71.     int segNo;        /* Segment number that is part of recovery log. */
  72.     int    blockOffset;    /* Starting block offset into that segment. */
  73. {
  74.     if (segInfoArray == (SegInfo *) NULL) {
  75.     segInfoArray = (SegInfo *) 
  76.             calloc(lfsPtr->superBlock.usageArray.numberSegments, 
  77.                sizeof(segInfoArray[0]));
  78.     if (segInfoArray == (SegInfo *) NULL) {
  79.         fprintf(stderr,"Can't allocate memory for segInfoArray\n");
  80.         exit(1);
  81.     }
  82.     logPosition = 0;
  83.     }
  84.  
  85.     if (segInfoArray[segNo].logPosition == 0) {
  86.     segInfoArray[segNo].logPosition = ++logPosition;
  87.     segInfoArray[segNo].startLogBlockOffset = blockOffset;
  88.     }
  89.  
  90. }
  91.  
  92. /*
  93.  *----------------------------------------------------------------------
  94.  *
  95.  * SegIsPartOfLog --
  96.  *
  97.  *    Check to see if segment is part of the recovery log.
  98.  *
  99.  * Results:
  100.  *    TRUE if part of recovery log, FALSE otherwise.
  101.  *
  102.  * Side effects:
  103.  *    None.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107.  
  108. Boolean 
  109. SegIsPartOfLog(segNo)
  110.     int    segNo;    /* Segment number of check. */
  111. {
  112.     return (segInfoArray[segNo].logPosition != 0);
  113. }
  114.  
  115. /*
  116.  *----------------------------------------------------------------------
  117.  *
  118.  * AddrOlderThan --
  119.  *
  120.  *    Return TRUE if address addr1 was written later in the log than
  121.  *    addr2.
  122.  *
  123.  * Results:
  124.  *    TRUE or FALSE
  125.  *
  126.  * Side effects:
  127.  *    None.
  128.  *
  129.  *----------------------------------------------------------------------
  130.  */
  131.  
  132. Boolean
  133. AddrOlderThan(addr1, addr2)
  134.     int       addr1;
  135.     int       addr2;
  136. {
  137.     int segNo1, segNo2;
  138.  
  139.     segNo1 = LfsDiskAddrToSegmentNum(lfsPtr, addr1);
  140.     segNo2 = LfsDiskAddrToSegmentNum(lfsPtr, addr2);
  141.     if (segNo1 == segNo2) {
  142.     /*
  143.      * Both blocks are in the same segment. Since we grow the
  144.      * segments backward a smaller address means an older block.
  145.      */
  146.      return (addr1 < addr2);
  147.     } else {
  148.     int age1, age2;
  149.     LfsSegUsageEntry *entryPtr;
  150.     /*
  151.      * The blocks are in different segments so we are use the
  152.      * segment log position to determine the relative age.
  153.      * A higher log position number means a newer block.  
  154.      * If neither address is part of the recover segment
  155.      * chain we use the timestamps the the seg usage 
  156.      * block to determine the age.
  157.      */
  158.     if ( segInfoArray[segNo1].logPosition + 
  159.          segInfoArray[segNo2].logPosition > 0) {
  160.          return (segInfoArray[segNo1].logPosition > 
  161.                 segInfoArray[segNo2].logPosition);
  162.      } 
  163.      entryPtr = LfsGetUsageArrayEntry(lfsPtr, segNo1);
  164.      age1 = entryPtr->timeOfLastWrite;
  165.      entryPtr = LfsGetUsageArrayEntry(lfsPtr, segNo2);
  166.      age2 = entryPtr->timeOfLastWrite;
  167.      return (age1 < age2);
  168.     }
  169. }
  170.  
  171.  
  172.  
  173. /*
  174.  *----------------------------------------------------------------------
  175.  *
  176.  * MarkSegDirty --
  177.  *
  178.  *    Mark the specified segment as nolonger being clean.
  179.  *
  180.  * Results:
  181.  *    None.
  182.  *
  183.  * Side effects:
  184.  *    None.
  185.  *
  186.  *----------------------------------------------------------------------
  187.  */
  188.  
  189. void
  190. MarkSegDirty(segNumber)
  191.     int    segNumber;    /* The segment which should be marked not clean. */
  192. {
  193.     LfsSegUsageEntry *entryPtr, *previousEntryPtr;
  194.     int    segNo, previousSegNo;
  195.     LfsSegUsageCheckPoint    *cp = &lfsPtr->usageArray.checkPoint;
  196.  
  197.     assert((segNumber >= 0) && 
  198.        (segNumber < lfsPtr->superBlock.usageArray.numberSegments));
  199.  
  200.     if (verboseFlag) {
  201.     printf("Marking segment %d as dirty\n", segNumber);
  202.     }
  203.     entryPtr = LfsGetUsageArrayEntry(lfsPtr, segNumber);
  204.     if (!(entryPtr->flags & LFS_SEG_USAGE_CLEAN)) {
  205.     printf("MarkSegDirty: Segment %d not clean.\n", segNumber);
  206.     return;
  207.     }
  208.     previousEntryPtr = (LfsSegUsageEntry *) NIL;
  209.     previousSegNo = -1;
  210.     segNo = cp->cleanSegList;
  211.     while ((segNo != segNumber) && (segNo != -1)) {
  212.     previousEntryPtr = LfsGetUsageArrayEntry(lfsPtr,segNo);
  213.     previousSegNo = segNo;
  214.     segNo = previousEntryPtr->activeBytes;
  215.     }
  216.     if (segNo != segNumber) {
  217.     panic("MarkSegDirty: Can't find segment on clean list.\n");
  218.     return;
  219.     }
  220.  
  221.     if (previousEntryPtr == (LfsSegUsageEntry *) NIL) {
  222.     cp->cleanSegList = entryPtr->activeBytes;
  223.     } else {
  224.     previousEntryPtr->activeBytes = entryPtr->activeBytes;
  225.     LfsUsageArrayEntryModified(lfsPtr, previousSegNo);
  226.     }
  227.  
  228.     entryPtr->flags = LFS_SEG_USAGE_DIRTY;
  229.     entryPtr->activeBytes = 0;
  230.     cp->numClean--;
  231.     cp->numDirty++;
  232.     LfsUsageArrayEntryModified(lfsPtr, segNumber);
  233. }
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * RecovSegUsageSummary --
  239.  *
  240.  *    Check the segment summary regions for the seg usage map. 
  241.  *
  242.  * Results:
  243.  *    None.
  244.  *
  245.  * Side effects:
  246.  *    None.
  247.  *
  248.  *----------------------------------------------------------------------
  249.  */
  250. extern void
  251. RecovSegUsageSummary(lfsPtr, pass, segPtr, startAddress, offset, 
  252.             segSummaryHdrPtr) 
  253.     Lfs    *lfsPtr;    /* File system description. */
  254.     enum Pass pass;    /* Pass number of recovery. */
  255.     LfsSeg *segPtr;    /* Segment being examined. */
  256.     int startAddress;   /* Starting address being examined. */
  257.     int offset;        /* Offset into segment being examined. */
  258.     LfsSegSummaryHdr *segSummaryHdrPtr; /* Summary header pointer */
  259. {
  260.     int blocks, *blockArray, i, startAddr, fsBlocks;
  261.  
  262.     if (pass == PASS2) {
  263.     /*
  264.      * Ignore seg usage array blocks during pass2 recovery.   These don't
  265.      * contain anything we wont recovery already with the current
  266.      * algorithm.
  267.      */
  268.     return;
  269.     }
  270.     /*
  271.      * During PASS1, we simply check to insure that things are not
  272.      * corrupted.
  273.      */
  274.     fsBlocks = lfsPtr->superBlock.usageArray.stableMem.blockSize/blockSize;
  275.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  276.                 sizeof(int);
  277.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  278.     fprintf(stderr,"%s:RecovSegUsageSummary: Wrong block count; is %d should be %s\n", deviceName, blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  279.     }
  280.     blockArray = (int *) (segSummaryHdrPtr + 1);
  281.     for (i = 0; i < blocks; i++) {
  282.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  283.     if ((blockArray[i] < 0) || 
  284.         (blockArray[i] > lfsPtr->superBlock.usageArray.stableMem.maxNumBlocks)){
  285.        fprintf(stderr,"%s:RecovSegUsageSummary: Bad block number %d at %d\n",
  286.             deviceName,blockArray[i], startAddr);
  287.         continue;
  288.     }
  289.     if (showLog) {
  290.         printf("Addr %d UsageArray Block %d\n", startAddr, blockArray[i]);
  291.     }
  292.     }
  293.     stats.segUsageBlocks += blocks;
  294.  
  295. }
  296.  
  297. void
  298. RollSegUsageForward(lfsPtr)
  299.     Lfs    *lfsPtr;
  300. {
  301.     int    segNo, numSegs, oldCurrentSegment, currentSegment;
  302.     LfsSegUsageEntry *entryPtr;
  303.     LfsSegUsageCheckPoint    *cp = &lfsPtr->usageArray.checkPoint;
  304.  
  305.     if (verboseFlag) {
  306.     printf("RollSegUsageForward: Log end moving from <%d,%d> to <%d,%d>\n",
  307.         cp->currentSegment, cp->currentBlockOffset, logEnd.segNo,
  308.         logEnd.blockOffset);
  309.     }
  310.     /*
  311.      * Move the tail of log forward. To new logend.
  312.      */
  313.     currentSegment = oldCurrentSegment = cp->currentSegment;
  314.     if (oldCurrentSegment == logEnd.segNo) {
  315.     /*
  316.      * Log stops in the same segment as last checkpoint.
  317.      */
  318.     cp->currentBlockOffset = logEnd.blockOffset;
  319.     } else {
  320.     entryPtr = LfsGetUsageArrayEntry(lfsPtr, oldCurrentSegment);
  321.     entryPtr->activeBytes = cp->curSegActiveBytes;
  322.     if (!(entryPtr->flags & LFS_SEG_USAGE_DIRTY) && 
  323.         (entryPtr->activeBytes <= cp->dirtyActiveBytes)) {
  324.         entryPtr->flags |= LFS_SEG_USAGE_DIRTY;
  325.         cp->numDirty++;
  326.     }
  327.     LfsUsageArrayEntryModified(lfsPtr, oldCurrentSegment);
  328.     MarkSegDirty(logEnd.segNo);
  329.     cp->currentSegment = logEnd.segNo;
  330.     cp->currentBlockOffset = logEnd.blockOffset;
  331.     cp->curSegActiveBytes = 0;
  332.     cp->previousSegment = -1;
  333.  
  334.     currentSegment = cp->currentSegment;
  335.     stats.numLogSegments++;
  336.     }
  337.  
  338.  
  339.     /*
  340.      * First besure that any segment that is part of the recovery
  341.      * log is marked as not clean. 
  342.      */
  343.     numSegs = lfsPtr->superBlock.usageArray.numberSegments;
  344.     for (segNo = 0; segNo < numSegs; segNo++) {
  345.     /*
  346.      * Skip segments that are not part of the recovery log or
  347.      * are the current segment being written. 
  348.      */
  349.     if (SegIsPartOfLog(segNo) && (segNo != currentSegment)) {
  350.         stats.numLogSegments++;
  351.         MarkSegDirty(segNo);
  352.     }
  353.     }
  354. }
  355.  
  356.